package com.aiti.lulian.service.newCard;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.WorkbookUtil;
import com.aiti.base.core.constant.MessageCodeConstant;
import com.aiti.base.core.exception.BusinessException;
import com.aiti.base.core.page.PageInfo;
import com.aiti.base.core.page.PageResult;
import com.aiti.base.core.utils.message.Message;
import com.aiti.lulian.constant.MiniProgramVersionConstant;
import com.aiti.lulian.constant.NewCardBusinessConstant;
import com.aiti.lulian.dto.newCard.*;
import com.aiti.lulian.entity.CardEnterpriseTemplate;
import com.aiti.lulian.entity.LuLianEnterprise;
import com.aiti.lulian.entity.LuLianEnterpriseUser;
import com.aiti.lulian.entity.newCard.*;
import com.aiti.lulian.gxmh.dto.SysUserDto;
import com.aiti.lulian.mapper.CardEnterpriseTemplateMapper;
import com.aiti.lulian.mapper.CardTemplateStyleFieldMapper;
import com.aiti.lulian.mapper.LuLianEnterpriseMapper;
import com.aiti.lulian.mapper.LuLianEnterpriseUserMapper;
import com.aiti.lulian.mapper.gxmh.GxmhSysMapper;
import com.aiti.lulian.mapper.newCard.*;
import com.aiti.lulian.service.CardUserCardForwardCoverOptionService;
import com.aiti.lulian.vo.newCard.*;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * description:
 * auth fcb
 * date 2025-09-08 13:44
 **/
@Service
@Slf4j
public class CardEnterpriseUserService {

    private static final String MUST_FILL = "（必填）";

    @Autowired
    private LuLianEnterpriseMapper luLianEnterpriseMapper;
    @Autowired
    private ShowEnterpriseTrialMapper showEnterpriseTrialMapper;
    @Autowired
    private CardEnterpriseTemplateMapper cardEnterpriseTemplateMapper;
    @Autowired
    private CardEnterpriseTemplateNewMapper cardEnterpriseTemplateNewMapper;
    @Autowired
    private CardEnterpriseTemplateNewService cardEnterpriseTemplateNewService;
    @Autowired
    private CardTemplateStyleFieldMapper cardTemplateStyleFieldMapper;
    @Autowired
    private CardStyleFieldDataMapper cardStyleFieldDataMapper;
    @Autowired
    private CardStyleFieldDataService cardStyleFieldDataService;
    @Autowired
    private CardEnterpriseQrMapper cardEnterpriseQrMapper;
    @Autowired
    private CardAuditMapper cardAuditMapper;
    @Autowired
    private CardPersonalBaseInfoMapper cardPersonalBaseInfoMapper;
    @Autowired
    private CardPersonalBaseInfoService cardPersonalBaseInfoService;
    @Autowired
    private CardEnterpriseComponentMapper cardEnterpriseComponentMapper;
    @Autowired
    private CardComponentDataService cardComponentDataService;
    @Autowired
    private CardComponentDataMapper cardComponentDataMapper;
    @Autowired
    private CardAuditService cardAuditService;
    @Autowired
    private GxmhSysMapper gxmhSysMapper;
    @Autowired
    private LuLianEnterpriseUserMapper luLianEnterpriseUserMapper;
    @Autowired
    private CardShareConfigService cardShareConfigService;
    @Autowired
    private CardUserCardForwardCoverOptionService cardUserCardForwardCoverOptionService;
    @Autowired
    private CardPrivacySettingMapper cardPrivacySettingMapper;


    /**
     * 获取企业管理员邀请用户信息
     * @param enterpriseId
     * @param templateId
     * @param inviteUUserId 发出邀请的人用户id
     * @Param type 1: 企业管理后台生成二维码邀请 2: 小程序端直接邀请
     *        type == 1时，auditBaseId存在，auditBaseId == no时，是第一种邀请类型（用户填写表单到审核）
     * @return
     */
    public EnterpriseAdminInviteUserVo getEnterpriseAdminInviteUserInfo(String enterpriseId, String templateId, String inviteUserId, String type, String auditBaseId) {
        if("1".equals(type)) {
            Integer quType = null;
            if(StrUtil.isBlank(auditBaseId)) {
                log.error("获取企业管理员邀请用户信息，参数错误。未传auditBaseId");
                throw new BusinessException("参数错误");
            }
            if("no".equals(auditBaseId)) {
                quType = 1;
            }else {
                quType = 2;
            }
            // 1. 判断该企业当前模板的二维码是否到期
            EnterpriseCardQRVo enterpriseCardQRVo = cardEnterpriseQrMapper.queryEnterpriseQR(enterpriseId, templateId, quType, auditBaseId);
            if (enterpriseCardQRVo == null) {
                throw new BusinessException("未查询到当前模板邀请二维码");
            }
            if (enterpriseCardQRVo.getExpireTimeType() == 2) {
                DateTime expireTime = DateUtil.parse(enterpriseCardQRVo.getExpireTime());
                if (expireTime.isBefore(new Date())) {
                    throw new BusinessException("二维码已过期");
                }
            }
        }
        EnterpriseAdminInviteUserVo vo = new EnterpriseAdminInviteUserVo();
        // 2. 查询企业信息
        LuLianEnterprise luLianEnterprise = luLianEnterpriseMapper.selectById(enterpriseId);
        if(luLianEnterprise != null) {
            vo.setEnterpriseName(luLianEnterprise.getBaseName());
            vo.setEnterpriseLogo(luLianEnterprise.getLogo());
        }else {
            ShowEnterpriseTrial showEnterpriseTrial = showEnterpriseTrialMapper.selectById(enterpriseId);
            if(showEnterpriseTrial != null) {
                vo.setEnterpriseName(showEnterpriseTrial.getBaseName());
                vo.setEnterpriseLogo(showEnterpriseTrial.getLogo());
            }else {
                throw new BusinessException("未查询到当前企业信息");
            }
        }
        // 3. 查询模板信息
        CardEnterpriseTemplateNew cardEnterpriseTemplateNew = cardEnterpriseTemplateNewMapper.selectById(templateId);
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
        vo.setTemplateName(cardEnterpriseTemplateNew.getTemplateName());
        vo.setTemplatePic(cardEnterpriseTemplate.getTemplatePic());
        // 4. 查询发出邀请的人的基于当前模板生成的名片字段数据
        // 邀请人该模板下的名片id
        CardAudit cardAudit = cardAuditMapper.queryCardAuditInfo(enterpriseId, templateId, inviteUserId, NewCardBusinessConstant.CARD_STATUS_3);
        // 如果该邀请人不在当前模板之下，查询该邀请人最早加入的模板的名片数据。从这张名片中取姓名和职位
        List<CardStyleFieldData> cardStyleFieldData;
        if(cardAudit != null) {
            // 名片的字段数据
           cardStyleFieldData = cardStyleFieldDataMapper.queryListByCardId(cardAudit.getCardId());
        }else {
            CardAudit cardAuditFirst = cardAuditMapper.queryUserFirstJoinAudit(enterpriseId, inviteUserId);
            if(cardAuditFirst == null) {
                throw new BusinessException("未查询到邀请人的名片数据");
            }
            cardStyleFieldData = cardStyleFieldDataMapper.queryListByCardId(cardAuditFirst.getCardId());
        }
        // 该模板的字段数据
        List<CardTemplateStyleFieldBo> cardTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        CardFieldBo nameField = existFieldName("姓名", cardTemplateStyleFields);
        CardFieldBo positionField = existFieldName("职位", cardTemplateStyleFields);
        if(!nameField.getExist()) {
            vo.setName(vo.getEnterpriseName());
        }else {
            // 从名片数据中找到姓名
            vo.setName(this.findValue(cardStyleFieldData, nameField));
        }
        if(!positionField.getExist()) {
            vo.setPosition("");
        }else {
            // 从名片数据中找到职位
            vo.setPosition(this.findValue(cardStyleFieldData, positionField));
        }
        // 5. 已经领取名片的同事的数量
        Integer alreadyGetCardCount = cardAuditMapper.queryCardAuditCount(enterpriseId, templateId, NewCardBusinessConstant.CARD_STATUS_3);
        vo.setAlreadyGetCardCount(alreadyGetCardCount);

        // todo 头像

        return vo;
    }

    /**
     * 获取模板的字段列表
     * @param templateId
     * @return
     */
    public List<StyleFieldDto> getStyleFieldList(String templateId) {
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
        List<StyleFieldDto> styleFieldList = cardTemplateStyleFieldMapper.queryStyleFieldByTemplateId(cardEnterpriseTemplate.getBaseId());
        String enterpriseName = "";
        LuLianEnterprise luLianEnterprise = luLianEnterpriseMapper.selectById(cardEnterpriseTemplate.getEnterpriseId());
        if(luLianEnterprise == null) {
            ShowEnterpriseTrial showEnterpriseTrial = showEnterpriseTrialMapper.selectById(cardEnterpriseTemplate.getEnterpriseId());
            enterpriseName = showEnterpriseTrial.getBaseName();
        }else {
            enterpriseName = luLianEnterprise.getBaseName();
        }
        for(StyleFieldDto styleFieldDto : styleFieldList) {
            if("公司".equals(styleFieldDto.getFieldName())) {
                styleFieldDto.setFieldValue(enterpriseName);
            }
        }
        return styleFieldList;
    }


    /**
     * 创建企业用户名片。小程序端用户填写表单方式
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Message createEnterpriseUserCard(CreateEnterpriseUserCardDto dto) {
        Message checkParamMessage = this.checkParam(dto);
        if(checkParamMessage != null) {
            return checkParamMessage;
        }
        // 1. 检查当前用户在该企业的模板下是否已经存在名片
        String existCardId = cardPersonalBaseInfoMapper.queryEnterpriseCardId(dto.getEnterpriseId(), dto.getTemplateId(), dto.getUserId());
        if(StrUtil.isNotEmpty(existCardId)) {
            CardAudit cardAudit = cardAuditMapper.queryCardAuditInfoByCardId(existCardId);
            if(NewCardBusinessConstant.CARD_STATUS_2.equals(cardAudit.getCardStatus())) {
                JSONObject obj = new JSONObject();
                obj.put("cardId", existCardId);
                obj.put("enterpriseId", dto.getEnterpriseId());
                obj.put("templateId", dto.getTemplateId());
                return new Message(MessageCodeConstant.MSG_EXCEPTION_CODE, "该模板下您已有一张企业名片在审核，请联系管理员", obj);
            }
            if(NewCardBusinessConstant.CARD_STATUS_3.equals(cardAudit.getCardStatus())) {
                JSONObject obj = new JSONObject();
                obj.put("cardId", existCardId);
                obj.put("enterpriseId", dto.getEnterpriseId());
                obj.put("templateId", dto.getTemplateId());
                return new Message(MessageCodeConstant.MSG_EXCEPTION_CODE, "该模板下您已有一张企业名片，请勿重复领取", obj);
            }
        }
        // 2. 创建名片数据
        CardBaseInfo cardBaseInfo = this.buildCardBaseInfo(dto);
        cardPersonalBaseInfoMapper.insert(cardBaseInfo);
        // 2.1 初始化名片隐私设置
        cardPrivacySettingMapper.insert(CardPrivacySetting.builder().baseId(IdUtil.simpleUUID()).userId(cardBaseInfo.getUserId()).cardId(cardBaseInfo.getBaseId()).baseUpdateTime(new Date()).build());
        // 3. 创建名片数据--卡片字段数据
        this.createCardFieldData(dto, cardBaseInfo.getBaseId());
        // 4. 创建名片数据--名片组件数据
        List<CardEnterpriseComponent> templateComponentList = cardEnterpriseComponentMapper.queryCardEnterpriseComponentList(dto.getTemplateId());
        cardComponentDataService.createCardComponentData(templateComponentList, cardBaseInfo.getBaseId());
        // 创建转发封面信息
        CardShareConfig cardShareConfig = cardShareConfigService.queryCardShareConfig(dto.getEnterpriseId(), dto.getTemplateId());
        cardUserCardForwardCoverOptionService.createDefaultForwardCover(dto.getUserId(), cardBaseInfo.getBaseId(), cardShareConfig.getCoverUrl(), cardShareConfig.getType(), cardShareConfig.getCoverUrlBaseId());
        // 5. 将用户添加到企业之下。
        this.bindEnterprise(dto.getEnterpriseId(), dto.getUserId());
        // 设置个人角色
        this.insertUserRole(dto.getEnterpriseId(), dto.getUserId());
        // 6. 加入待审核列表
        CardAudit cardAudit = this.addToAudit(dto.getEnterpriseId(), dto.getTemplateId(), cardBaseInfo.getBaseId(), dto.getUserId(), NewCardBusinessConstant.CARD_STATUS_2);
        cardAuditService.save(cardAudit);
        return Message.success();
    }

    /**
     * 从小程序端领取名片。名片数据已被企业管理员录入
     * @param userId 员工id
     * @param auditBaseId card_audit表主键
     */
    @Transactional(rollbackFor = Exception.class)
    public Message getMyCard(String userId, String auditBaseId) {
        if(StrUtil.isBlank(auditBaseId) || StrUtil.isBlank(userId)) {
            return Message.fail("参数错误");
        }
        CardAudit audit = cardAuditMapper.selectById(auditBaseId);
        if(audit == null || 1 == audit.getIsDelete()) {
            return Message.fail("该邀请已被删除");
        }
        SysUserDto sysUserDto = gxmhSysMapper.queryUserInfo(userId);
        if(sysUserDto == null) {
            return Message.fail("用户不存在");
        }
        String existCardId = cardPersonalBaseInfoMapper.queryEnterpriseCardId(audit.getEnterpriseId(), audit.getTemplateId(), userId);
        if(StrUtil.isNotEmpty(existCardId)) {
            CardAudit cardAudit = cardAuditMapper.queryCardAuditInfoByCardId(existCardId);
            if(NewCardBusinessConstant.CARD_STATUS_2.equals(cardAudit.getCardStatus())) {
                JSONObject obj = new JSONObject();
                obj.put("cardId", existCardId);
                obj.put("enterpriseId", audit.getEnterpriseId());
                obj.put("templateId", audit.getTemplateId());
                return new Message(MessageCodeConstant.MSG_EXCEPTION_CODE, "该模板下您已有一张企业名片在审核，请联系管理员", obj);
            }
            if(NewCardBusinessConstant.CARD_STATUS_3.equals(cardAudit.getCardStatus())) {
                JSONObject obj = new JSONObject();
                obj.put("cardId", existCardId);
                obj.put("enterpriseId", audit.getEnterpriseId());
                obj.put("templateId", audit.getTemplateId());
                return new Message(MessageCodeConstant.MSG_EXCEPTION_CODE, "该模板下您已有一张企业名片，请勿重复领取", obj);
            }
        }
        CardBaseInfo cardInfo = cardPersonalBaseInfoMapper.selectById(audit.getCardId());
        if(StrUtil.isBlank(cardInfo.getEnterpriseMobile())) {
            return new Message(MessageCodeConstant.MSG_EXCEPTION_CODE, "未获取到管理员所填手机号，请联系管理员设置手机号", null);
        }
        if(!cardInfo.getEnterpriseMobile().equals(sysUserDto.getUsername())) {
            return new Message(MessageCodeConstant.MSG_EXCEPTION_CODE, "您授权的手机号与管理员所填手机号不一致，请联系管理员修改", null);
        }
        // 1. 将该用户加入企业
        this.bindEnterprise(audit.getEnterpriseId(), userId);
        this.insertUserRole(audit.getEnterpriseId(), userId);
        // 2. 更新名片表关联字段
        CardBaseInfo cardBaseInfo = new CardBaseInfo();
        cardBaseInfo.setBaseId(audit.getCardId());
        cardBaseInfo.setUserId(userId);
        cardBaseInfo.setEnterpriseId(audit.getEnterpriseId());
        cardBaseInfo.setTemplateId(audit.getTemplateId());
        cardBaseInfo.setBaseUpdateTime(new Date());
        cardBaseInfo.setBaseUpdateBy(userId);
        // 这里再设置一次是否在用，是因为在用Excel导入的时候没有设置该字段
        Integer currentUse = cardPersonalBaseInfoMapper.queryCurrentUseCardCount(userId);
        cardBaseInfo.setCurrentUse(currentUse == 0 ? 1 : 0);
        cardPersonalBaseInfoMapper.updateById(cardBaseInfo);
        // 这里将改名片的隐私设置初始化出来
        cardPrivacySettingMapper.insert(CardPrivacySetting.builder().baseId(IdUtil.simpleUUID()).userId(cardBaseInfo.getUserId()).cardId(cardBaseInfo.getBaseId()).baseUpdateTime(new Date()).build());
        // 这里创建名片的转发配置，导入excel的时候没有创建转发配置，因为没有用户id
        CardShareConfig cardShareConfig = cardShareConfigService.queryCardShareConfig(audit.getEnterpriseId(), audit.getTemplateId());
        cardUserCardForwardCoverOptionService.createDefaultForwardCover(userId, cardBaseInfo.getBaseId(), cardShareConfig.getCoverUrl(), cardShareConfig.getType(), cardShareConfig.getCoverUrlBaseId());
        // 3. 修改审核表
        audit.setUserId(userId);
        audit.setCardStatus(NewCardBusinessConstant.CARD_STATUS_3);
        audit.setActiveTime(new Date());
        audit.setBaseUpdateTime(new Date());
        audit.setBaseUpdateBy(userId);
        cardAuditMapper.updateById(audit);

        return Message.success();
    }

    /**
     * 管理员录入方式创建员工名片数据.
     * 此时仅是生成名片相关数据，该名片所属用户可能还不存在
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void createEnterpriseUserCard2(CreateEnterpriseUserCardDto dto, String loginUserId) {
        if(StrUtil.isBlank(dto.getEnterpriseId()) || StrUtil.isBlank(dto.getTemplateId())) {
            throw new BusinessException("参数错误");
        }
        // 0. 判断所填的手机号字段所对应的账号是否在该模板下已经存在
        String mobile = this.findMobile(dto);
        if(StrUtil.isNotBlank(mobile)) {
            // 判断修改的手机号码是否已经存在了名片
            // 这里先使用用户id去判断。如果用用户id判断，
            // 有一种情况导致所有的手机号都不同，但是却无法保存，
            // 比如：有一个用户是审核通过的，他的手机号（158xxx）和用户id都是他本人的，此时他企业管理员修改他的手机号改成别的（134xxx），此时再新录入一个员工，手机号是158xxx，此时没有相同的手机号，但是这个158的账号在用户表中关联的是158的用户（他的手机号已经被改了），此时会无法添加
            String userId = gxmhSysMapper.queryUserIdByUsername(mobile);
            this.checkUserIdExist(dto.getTemplateId(), userId);
            this.checkMobileExist(dto.getEnterpriseId(), dto.getTemplateId(), mobile,null);
        }
        // 1. 创建名片数据
        CardBaseInfo cardBaseInfo = this.buildCardBaseInfo(dto);
        // 2. 将关联字段设置为null
        cardBaseInfo.setUserId(null);
        cardBaseInfo.setEnterpriseId(null);
        cardBaseInfo.setTemplateId(null);
        cardPersonalBaseInfoMapper.insert(cardBaseInfo);
        // 3. 创建名片数据--卡片字段数据
        this.createCardFieldData(dto, cardBaseInfo.getBaseId());
        // 4. 创建名片数据--名片组件数据
        List<CardEnterpriseComponent> templateComponentList = cardEnterpriseComponentMapper.queryCardEnterpriseComponentList(dto.getTemplateId());
        cardComponentDataService.createCardComponentData(templateComponentList, cardBaseInfo.getBaseId());
        // 5. 加入待激活列表
        CardAudit cardAudit = this.addToAudit(dto.getEnterpriseId(), dto.getTemplateId(), cardBaseInfo.getBaseId(), null, NewCardBusinessConstant.CARD_STATUS_1);
        cardAudit.setBaseCreateBy(loginUserId);
        cardAudit.setBaseUpdateBy(loginUserId);
        cardAuditService.save(cardAudit);
    }

    // 判断修改的手机号所对应的用户是不是已经存在在模板之下
    private void checkUserIdExist(String templateId, String userId) {
        if(StrUtil.isNotBlank(userId)) {
            // 已审核数量
            Integer cardCount = cardAuditMapper.queryCardAuditTemplateUserCount(userId, templateId, NewCardBusinessConstant.CARD_STATUS_3);
            if (cardCount > 0) {
                throw new BusinessException("该模板下已存在该手机号的员工的名片");
            }
            // 待审核数量
            Integer noAuditCardCount = cardAuditMapper.queryCardAuditTemplateUserCount(userId, templateId, NewCardBusinessConstant.CARD_STATUS_2);
            if (noAuditCardCount > 0) {
                throw new BusinessException("该手机号已存在待审核列表中");
            }
        }

    }

    // 这里的手机号不是登录用户名，是名片上的，enterprise_mobile或者叫“手机”的字段
    // 判断手机号是不是存在目标模板下待激活列表中
    private void checkMobileExist(String enterpriseId, String templateId, String mobile, String cardId) {
        Integer noActiveCount = cardAuditMapper.queryEnterpriseNoActiveCount(enterpriseId, templateId, mobile, cardId);
        if (noActiveCount > 0) {
            throw new BusinessException("该手机号与已有数据的手机号重复");
        }
    }

    private String findMobile(CreateEnterpriseUserCardDto dto) {
        if(CollectionUtil.isEmpty(dto.getStyleFieldList())) {
            return null;
        }
        for(StyleFieldDto fieldDto : dto.getStyleFieldList()) {
            if("手机".equals(fieldDto.getFieldName())) {
                String mobile = fieldDto.getFieldValue();
                return mobile;
            }
        }
        return null;
    }

    /**
     * 企业管理页面查询模板下用户列表
     * @param queryDto
     * @return
     */
    public PageResult<EnterpriseUserCardVo> queryEnterpriseUserCardList(EnterpriseUserCardSearchDto queryDto) {
        String enterpriseAdminUserId = gxmhSysMapper.queryEnterpriseAdminUserId(queryDto.getEnterpriseId());
        if(StrUtil.isBlank(enterpriseAdminUserId)) {
            throw new BusinessException("未查询到该企业的企业管理员");
        }
        IPage<EnterpriseUserCardVo> page = new Page<>(queryDto.getPageNum(), queryDto.getPageSize());
        List<EnterpriseUserCardVo> list = cardAuditMapper.queryEnterpriseUserCardList(page, queryDto);
        for(EnterpriseUserCardVo vo : list) {
            if(enterpriseAdminUserId.equals(vo.getUserId())) {
                vo.setIsEnterpriseAdmin(true);
                break;
            }
        }
        PageResult<EnterpriseUserCardVo> pageResult = new PageResult<>(list, new PageInfo(queryDto.getPageNum(), queryDto.getPageSize()), page.getTotal());
        return pageResult;
    }

    /**
     * 判断用户是否是该企业的管理员
     * @param enterpriseId
     * @param userId
     * @return
     */
    public Boolean isEnterpriseAdmin(String enterpriseId, String userId) {
        String enterpriseAdminUserId = gxmhSysMapper.queryEnterpriseAdminUserId(enterpriseId);
        if(StrUtil.isBlank(enterpriseAdminUserId)) {
            throw new BusinessException("未查询到企业管理员");
        }
        return enterpriseAdminUserId.equals(userId);
    }

    /**
     * 申请加入企业列表
     * @param pageNum
     * @param pageSize
     * @param enterpriseId
     * @return
     */
    public PageResult<EnterpriseUserCardVo> queryEnterpriseApplyMsg(Integer pageNum, Integer pageSize, String enterpriseId) {
        IPage<EnterpriseUserCardVo> page = new Page<>(pageNum, pageSize);
        List<EnterpriseUserCardVo> list = cardAuditMapper.queryEnterpriseApplyMsg(page, enterpriseId);
        PageResult<EnterpriseUserCardVo> pageResult = new PageResult<>(list, new PageInfo(pageNum, pageSize), page.getTotal());
        return pageResult;
    }

    /**
     * 已加入企业的成员动态
     * @param pageNum
     * @param pageSize
     * @param enterpriseId
     * @return
     */
    public PageResult<EnterpriseUserCardVo> queryEnterpriseUserActive(Integer pageNum, Integer pageSize, String enterpriseId) {
        IPage<EnterpriseUserCardVo> page = new Page<>(pageNum, pageSize);
        List<EnterpriseUserCardVo> list = cardAuditMapper.queryEnterpriseUserActive(page, enterpriseId);
        PageResult<EnterpriseUserCardVo> pageResult = new PageResult<>(list, new PageInfo(pageNum, pageSize), page.getTotal());
        return pageResult;
    }

    /**
     * 这个接口应该是只有企业管理员可以调用，包括小程序和企业后端
     * @param cardId
     * @param auditStatus 1:同意，2：拒绝，3：移除， 4：删除待激活
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateCardAuditStatus(UpdateCardStatusDto dto) {
        List<CardAudit> cardAuditList = cardAuditMapper.selectBatchIds(dto.getAuditBaseIdList());
        if(CollectionUtil.isEmpty(cardAuditList)) {
            return;
        }
        Date now = new Date();
        if(1 == dto.getAuditStatus()) {
            cardAuditMapper.updateCardAuditStatus(dto.getAuditBaseIdList(), NewCardBusinessConstant.CARD_STATUS_3, dto.getUserId(), now, NewCardBusinessConstant.CARD_STATUS_2);
            return;
        }
        // 拒绝时只修改状态，名片数据保留。
        if(2 == dto.getAuditStatus()) {
            // todo 删除名片数据，后面可以改为物理删除
            cardAuditMapper.deleteCardAuditBatch(dto.getAuditBaseIdList(), dto.getUserId());
            List<String> cardIdList = cardAuditList.stream().map(CardAudit::getCardId).collect(Collectors.toList());
            // 逻辑删除名片数据
            cardPersonalBaseInfoMapper.deleteCardBaseInfoBatch(cardIdList, dto.getUserId());
            // 判断被移除的用户在该企业下是否还有名片
            for(CardAudit cardAudit : cardAuditList) {
                List<CardBaseInfo> cardBaseInfos = cardPersonalBaseInfoMapper.queryUserEnterpriseCardList(cardAudit.getUserId(), cardAudit.getEnterpriseId());
                if(CollectionUtil.isEmpty(cardBaseInfos)) {
                    luLianEnterpriseUserMapper.deleteUserEnterprise(cardAudit.getUserId(), cardAudit.getEnterpriseId());
                    // 如果有角色需要移除角色
                    gxmhSysMapper.deleteUserRoleEnterprise(cardAudit.getUserId(), cardAudit.getEnterpriseId());
                }
            }
        }
        // 移除操作，逻辑删除名片数据。判断被移除的名片所属用户是否在该企业下还有别的名片，如果没有则将该用户与企业的绑定关系移除
        if(3 == dto.getAuditStatus()) {
            // 判断当前被删除的这些用户是不是包含企业管理员，如果包含企业管理员，则判断这个企业管理员是不是仅存在当前模板下，如果是，则不允许删除
            List<String> userIdList = cardAuditList.stream().map(CardAudit::getUserId).collect(Collectors.toList());
            if(userIdList.contains(dto.getUserId())) {
                Integer adminCardCount = cardAuditMapper.queryEnterpriseUserCardCount(cardAuditList.get(0).getEnterpriseId(), dto.getUserId());
                if(adminCardCount == 1) {
                    throw new BusinessException("企业管理员不能被移除企业");
                }
            }
            cardAuditMapper.deleteCardAuditBatch(dto.getAuditBaseIdList(), dto.getUserId());
            List<String> cardIdList = cardAuditList.stream().map(CardAudit::getCardId).collect(Collectors.toList());
            cardPersonalBaseInfoMapper.deleteCardBaseInfoBatch(cardIdList, dto.getUserId());
            // 判断被移除的用户在该企业下是否还有名片
            for(CardAudit cardAudit : cardAuditList) {
                List<CardBaseInfo> cardBaseInfos = cardPersonalBaseInfoMapper.queryUserEnterpriseCardList(cardAudit.getUserId(), cardAudit.getEnterpriseId());
                if(CollectionUtil.isEmpty(cardBaseInfos)) {
                    luLianEnterpriseUserMapper.deleteUserEnterprise(cardAudit.getUserId(), cardAudit.getEnterpriseId());
                    // 如果有角色需要移除角色
                    gxmhSysMapper.deleteUserRoleEnterprise(cardAudit.getUserId(), cardAudit.getEnterpriseId());

                }
            }
        }
        // 批量删除待激活
        if(4 == dto.getAuditStatus()) {
            // 逻辑删除审核数据
            cardAuditMapper.deleteCardAuditBatch(dto.getAuditBaseIdList(), dto.getUserId());
            List<String> cardIdList = cardAuditList.stream().map(CardAudit::getCardId).collect(Collectors.toList());
            // 逻辑删除名片数据
            cardPersonalBaseInfoMapper.deleteCardBaseInfoBatch(cardIdList, dto.getUserId());
        }
    }

    /**
     * 获取卡片样式和数据，用于企业端编辑
     * @param templateId
     * @param cardId
     * @return
     */
    public CardStyleAndDataVo cardStyleAndDataDetail(String templateId, String cardId) {
        CardStyleAndDataVo vo = new CardStyleAndDataVo();
        // 1. 查询旧的模板表，获取模板基本样式
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
        vo.setCardUsedTemplateInfo(cardEnterpriseTemplate);
        // 2. 获取模板样式字段
        List<CardTemplateStyleFieldBo> cardTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        // 3. 获取名片的字段value数据
        List<CardStyleFieldData> cardStyleFieldDataList = cardStyleFieldDataMapper.queryListByCardId(cardId);
        // 4. 将字段样式的json内容中，text的值替换为字段value数据
        this.replaceTemplateTextValue(cardTemplateStyleFields, cardStyleFieldDataList);
        vo.setStyleFieldList(cardTemplateStyleFields);

        List<StyleFieldDto> styleFieldDtoList = this.buildStyleFieldDtoList(cardTemplateStyleFields, cardStyleFieldDataList);
        vo.setStyleFieldValueList(styleFieldDtoList);
        return vo;
    }

    /**
     * 查询当前企业下用户的所有名片数据
     * @param enterpriseId
     * @param userId
     * @return
     */
    public List<CardStyleAndDataVo> getUserAllCardStyleAndFieldData(String enterpriseId, String userId) {
        List<CardAudit> cardAudits = cardAuditMapper.queryCardAuditList(enterpriseId, userId);
        if(CollectionUtil.isEmpty(cardAudits)) {
            return new ArrayList<>();
        }
        List<CardStyleAndDataVo> cardStyleAndDataVoList = new ArrayList<>();
        for(CardAudit cardAudit : cardAudits) {
            CardStyleAndDataVo vo = new CardStyleAndDataVo();
            // 1. 查询旧的模板表，获取模板基本样式
            CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(cardAudit.getTemplateId());
            vo.setCardUsedTemplateInfo(cardEnterpriseTemplate);
            // 2. 获取模板样式字段
            List<CardTemplateStyleFieldBo> cardTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
            // 3. 获取名片的字段value数据
            List<CardStyleFieldData> cardStyleFieldDataList = cardStyleFieldDataMapper.queryListByCardId(cardAudit.getCardId());
            // 4. 将字段样式的json内容中，text的值替换为字段value数据
            this.replaceTemplateTextValue(cardTemplateStyleFields, cardStyleFieldDataList);
            vo.setStyleFieldList(cardTemplateStyleFields);
            vo.setCardStatus(cardAudit.getCardStatus());
            vo.setCardId(cardAudit.getCardId());
            cardStyleAndDataVoList.add(vo);
        }
        return cardStyleAndDataVoList;
    }

    public EnterpriseCardDetailVo getEnterpriseCardDetail(String cardId) {
        EnterpriseCardDetailVo vo = new EnterpriseCardDetailVo();
        CardAudit cardAudit = cardAuditMapper.queryCardAuditInfoByCardId(cardId);
        // 1. 查询旧的模板表，获取模板基本样式
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(cardAudit.getTemplateId());
        vo.setCardUsedTemplateInfo(cardEnterpriseTemplate);
        // 2. 获取模板样式字段
        List<CardTemplateStyleFieldBo> cardTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        // 3. 获取名片的字段value数据
        List<CardStyleFieldData> cardStyleFieldDataList = cardStyleFieldDataMapper.queryListByCardId(cardAudit.getCardId());
        // 4. 将字段样式的json内容中，text的值替换为字段value数据
        this.replaceTemplateTextValue(cardTemplateStyleFields, cardStyleFieldDataList);
        vo.setStyleFieldList(cardTemplateStyleFields);
        TemplateComponentVo memberComponentsInfo = cardEnterpriseTemplateNewService.getMemberComponentsInfo(cardAudit.getCardId());
        if(memberComponentsInfo == null) {
            vo.setComponentDataList(new ArrayList<>());
        }else {
            vo.setComponentDataList(memberComponentsInfo.getComponentDataList());
        }
        return vo;
    }

    /**
     * 获取模板的样式和字段，用于录入员工信息
     * @param templateId
     * @return
     */
    public CardStyleAndDataVo getTemplateStyleAndField(String templateId) {
        CardStyleAndDataVo vo = new CardStyleAndDataVo();
        // 1. 查询旧的模板表，获取模板基本样式
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
        vo.setCardUsedTemplateInfo(cardEnterpriseTemplate);
        // 2. 获取模板样式字段
        List<CardTemplateStyleFieldBo> cardTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        //List<StyleFieldDto> styleFieldDtoList = this.buildStyleFieldDtoList(cardTemplateStyleFields, new ArrayList<>());
        String enterpriseName = "";
        LuLianEnterprise luLianEnterprise = luLianEnterpriseMapper.selectById(cardEnterpriseTemplate.getEnterpriseId());
        if(luLianEnterprise == null) {
            ShowEnterpriseTrial showEnterpriseTrial = showEnterpriseTrialMapper.selectById(cardEnterpriseTemplate.getEnterpriseId());
            enterpriseName = showEnterpriseTrial.getBaseName();
        }else {
            enterpriseName = luLianEnterprise.getBaseName();
        }
        List<StyleFieldDto> styleFieldDtoList = new ArrayList<>();
        for(CardTemplateStyleFieldBo cardTemplateStyleFieldBo : cardTemplateStyleFields) {
            StyleFieldDto styleFieldDto = new StyleFieldDto();
            styleFieldDto.setFieldId(cardTemplateStyleFieldBo.getBaseId());
            styleFieldDto.setFieldName(cardTemplateStyleFieldBo.getBaseName());
            styleFieldDto.setFieldType(cardTemplateStyleFieldBo.getFieldType());
            if("公司".equals(styleFieldDto.getFieldName())) {
                styleFieldDto.setFieldValue(enterpriseName);
            }else if("地址".equals(styleFieldDto.getFieldName()) || "邮箱".equals(styleFieldDto.getFieldName())) {
                JSONObject jsonObject = JSONObject.parseObject(cardTemplateStyleFieldBo.getExtraInfo());
                styleFieldDto.setFieldValue(jsonObject.getString("text"));
            }else {
                styleFieldDto.setFieldValue("");
            }
            styleFieldDto.setRequiredFlag(cardTemplateStyleFieldBo.getRequiredFlag()?1:0);
            styleFieldDto.setFieldEngName(cardTemplateStyleFieldBo.getFieldName());
            styleFieldDtoList.add(styleFieldDto);
        }
        vo.setStyleFieldList(cardTemplateStyleFields);
        vo.setStyleFieldValueList(styleFieldDtoList);
        return vo;
    }

    private List<StyleFieldDto> buildStyleFieldDtoList(List<CardTemplateStyleFieldBo> cardTemplateStyleFields, List<CardStyleFieldData> cardStyleFieldDataList) {
        List<StyleFieldDto> styleFieldDtoList = new ArrayList<>();
        for(CardTemplateStyleFieldBo cardTemplateStyleFieldBo : cardTemplateStyleFields) {
            StyleFieldDto styleFieldDto = new StyleFieldDto();
            styleFieldDto.setFieldId(cardTemplateStyleFieldBo.getBaseId());
            styleFieldDto.setFieldName(cardTemplateStyleFieldBo.getBaseName());
            styleFieldDto.setFieldType(cardTemplateStyleFieldBo.getFieldType());
            styleFieldDto.setFieldValue(this.findValue2(cardStyleFieldDataList, cardTemplateStyleFieldBo.getBaseId()));
            styleFieldDto.setRequiredFlag(cardTemplateStyleFieldBo.getRequiredFlag()?1:0);
            styleFieldDto.setFieldEngName(cardTemplateStyleFieldBo.getFieldName());
            styleFieldDtoList.add(styleFieldDto);
        }
        return styleFieldDtoList;
    }

    /**
     * 切换模板
     * @param sourceTemplateId
     * @param targetTemplateId
     * @param cardId
     * @return
     */
    public CardStyleAndDataVo changeTemplate(String sourceTemplateId, String targetTemplateId, String cardId) {
        // 判断名片所属员工是否在目标模板下存在
        CardBaseInfo cardBaseInfo = cardPersonalBaseInfoMapper.selectById(cardId);
        Integer existUserCount = cardAuditMapper.queryCardAuditTemplateUserCount(cardBaseInfo.getUserId(), targetTemplateId, NewCardBusinessConstant.CARD_STATUS_3);
        if(existUserCount > 0 && !sourceTemplateId.equals(targetTemplateId)) {
            throw new BusinessException("当前员工已在目标模板下");
        }
        CardStyleAndDataVo vo = new CardStyleAndDataVo();
        // 1. 从旧模板表中查询目标模板的样式
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(targetTemplateId);
        vo.setCardUsedTemplateInfo(cardEnterpriseTemplate);
        // 2. 获取目标模板样式字段
        List<CardTemplateStyleFieldBo> targetTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        // 3. 获取名片的字段value数据
        List<CardStyleFieldData> cardStyleFieldDataList = cardStyleFieldDataMapper.queryListByCardId(cardId);
        // 4. 获取源模板的样式字段
        CardEnterpriseTemplate sourceEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(sourceTemplateId);
        List<CardTemplateStyleFieldBo> sourceTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(sourceEnterpriseTemplate.getBaseId());
        // 5. 构建源模板的字段value数据
        List<StyleFieldDto> sourceStyleFieldDtoList = this.buildStyleFieldDtoList(sourceTemplateStyleFields, cardStyleFieldDataList);
        // 6. 构建目标模板的字段value数据
        List<StyleFieldDto> targetStyleFieldDtoList = this.getStyleFieldDtoList(targetTemplateStyleFields, sourceStyleFieldDtoList);
        vo.setStyleFieldValueList(targetStyleFieldDtoList);
        //  7. 将目标模板字段样式的json内容中，text的值替换为字段value数据
        this.dealStyleFieldExtInfo(targetTemplateStyleFields, targetStyleFieldDtoList);
        vo.setStyleFieldList(targetTemplateStyleFields);
        return vo;
    }

    /**
     * 企业管理端修改名片字段值
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateCardFieldValue(CreateEnterpriseUserCardDto dto) {
        if (StrUtil.isEmpty(dto.getCardId())) {
            throw new BusinessException("名片ID不能为空");
        }
        CardAudit cardAudit = cardAuditMapper.queryCardAuditInfoByCardId(dto.getCardId());
        CardBaseInfo cardBaseInfo = cardPersonalBaseInfoMapper.selectById(dto.getCardId());
        String mobile = this.findMobile(dto);
        // 非切换模板保存
        if(StrUtil.isBlank(dto.getTargetTemplateId())) {
            // 根据当前名片的状态，判断是否校验用户修改的手机号是否已经存在名片。如果名片是待激活状态，则判断手机号是否已经有了别的状态的名片。
            // 全能王允许将已经审核通过、待审核的名片改成相同的手机号。所以只有待激活的时候需要判断
            if(NewCardBusinessConstant.CARD_STATUS_1.equals(cardAudit.getCardStatus())) {
                // 判断修改的手机号码是否已经存在了名片
                if (StrUtil.isNotEmpty(mobile)) {
                    // 这里先使用用户id去判断。如果用用户id判断，
                    // 有一种情况导致所有的手机号都不同，但是却无法保存，
                    // 比如：有一个用户是审核通过的，他的手机号（158xxx）和用户id都是他本人的，此时他企业管理员修改他的手机号改成别的（134xxx），此时再新录入一个员工，手机号是158xxx，此时没有相同的手机号，但是这个158的账号在用户表中关联的是158的用户（他的手机号已经被改了），此时会无法添加
                    String userId = gxmhSysMapper.queryUserIdByUsername(mobile);
                    this.checkUserIdExist(cardAudit.getTemplateId(), userId);
                    this.checkMobileExist(cardAudit.getEnterpriseId(), cardAudit.getTemplateId(), mobile, cardAudit.getCardId());
                }
            }
            // 删除该名片下的所有字段值数据
            cardStyleFieldDataService.remove(new LambdaQueryWrapper<CardStyleFieldData>().eq(CardStyleFieldData::getCardId, dto.getCardId()));
            // 重新保存修改之后的数据
            this.createCardFieldData(dto, dto.getCardId());
            // 修改card_base_info表可能存在的字段
            this.updateCardBaseInfo(dto.getCardId(), dto);
        }
        // 切换模板后保存
        else {
            // 判断所填的手机号对应的用户是否已经存在在目标模板之下，如果切换的是待激活的，判断目标模板下待激活的是否重复
            if (StrUtil.isNotEmpty(mobile)) {
                String userId = gxmhSysMapper.queryUserIdByUsername(mobile);
                this.checkUserIdExist(dto.getTargetTemplateId(), userId);
                if(NewCardBusinessConstant.CARD_STATUS_1.equals(cardAudit.getCardStatus())) {
                    this.checkMobileExist(cardAudit.getEnterpriseId(), dto.getTargetTemplateId(), mobile, null);
                }
            }
            // 删除该名片下的所有字段值数据
            cardStyleFieldDataService.remove(new LambdaQueryWrapper<CardStyleFieldData>().eq(CardStyleFieldData::getCardId, dto.getCardId()));
            // 重新保存修改之后的数据
            this.createCardFieldData(dto, dto.getCardId());
            // 修改card_base_info表可能存在的字段
            this.updateCardBaseInfo(dto.getCardId(), dto);
            // 删除该名片的组件数据，复制目标模板的组件数据作为当前名片的组件数据
            cardComponentDataService.remove(new LambdaQueryWrapper<CardComponentData>().eq(CardComponentData::getCardId, dto.getCardId()));
            List<CardEnterpriseComponent> cardEnterpriseComponents = cardEnterpriseComponentMapper.queryCardEnterpriseComponentList(dto.getTargetTemplateId());
            cardComponentDataService.createCardComponentData(cardEnterpriseComponents, dto.getCardId());
            // 如果是审核通过或待审核的名片，将名片的所属模板改为目标模板，待激活状态还没有绑定模板
            if (NewCardBusinessConstant.CARD_STATUS_3.equals(cardAudit.getCardStatus()) || NewCardBusinessConstant.CARD_STATUS_2.equals(cardAudit.getCardStatus())) {
                cardPersonalBaseInfoMapper.updateCardTemplateId(dto.getCardId(), dto.getTargetTemplateId(), dto.getUserId());
            }
            // 修改审批表模板字段
            cardAuditMapper.updateTemplateId(dto.getCardId(), dto.getTargetTemplateId(), dto.getUserId());
        }
        // 保存并同意审核
        if(dto.getSaveAndAgree() != null && dto.getSaveAndAgree() == 1) {
            List<String> auditBaseIdList = new ArrayList<>();
            auditBaseIdList.add(cardAudit.getBaseId());
            cardAuditMapper.updateCardAuditStatus(auditBaseIdList, NewCardBusinessConstant.CARD_STATUS_3, dto.getUserId(), new Date(), NewCardBusinessConstant.CARD_STATUS_2);
        }
    }

    /**
     * 批量修改名片模板。
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchChangeTemplate(BatchChangeTemplateDto dto) {
//        if(CollectionUtil.isEmpty(dto.getCardIdList()) || dto.getCardIdList().size() > 5) {
//            throw new BusinessException("目前仅支持同时修改最多5名员工模板");
//        }
        String targetTemplateId = dto.getTargetTemplateId();
        Map<String, String> cardIdAndTemplateIdMap = new HashMap<>();
        for(String cardId : dto.getCardIdList()) {
            // 判断名片所属员工是否在目标模板下存在
            CardBaseInfo cardBaseInfo = cardPersonalBaseInfoMapper.selectById(cardId);
            Integer existUserCount = cardAuditMapper.queryCardAuditTemplateUserCount(cardBaseInfo.getUserId(), targetTemplateId, NewCardBusinessConstant.CARD_STATUS_3);
            if(existUserCount > 0) {
                throw new BusinessException("所选员工中，存在员工名片已经在目标模板下存在");
            }
            cardIdAndTemplateIdMap.put(cardId, cardBaseInfo.getTemplateId());
        }
        for(String cardId : dto.getCardIdList()) {
            // 查询名片当前使用的模板字段列表
            String sourceTemplateId = cardIdAndTemplateIdMap.get(cardId);
            CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(sourceTemplateId);
            List<CardTemplateStyleFieldBo> sourceTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
            // 查询当前名片的字段值列表
            List<CardStyleFieldData> cardStyleFieldDataList = cardStyleFieldDataMapper.queryListByCardId(cardId);
            // 查询目标模板的字段列表
            CardEnterpriseTemplate targetEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(targetTemplateId);
            List<CardTemplateStyleFieldBo> targetTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(targetEnterpriseTemplate.getBaseId());
            // 根据目标模板的字段，构建新的名片字段数据。依据字段名称一样匹配
            List<CardStyleFieldData> newCardStyleFieldDataList = new ArrayList<>();
            for(CardTemplateStyleFieldBo targetTemplateStyleField : targetTemplateStyleFields) {
                CardStyleFieldData newCardStyleFieldData = new CardStyleFieldData();
                newCardStyleFieldData.setBaseId(IdUtil.simpleUUID());
                newCardStyleFieldData.setStyleFieldId(targetTemplateStyleField.getBaseId());
                newCardStyleFieldData.setCardId(cardId);
                String fieldValue = null;
                for(CardTemplateStyleFieldBo sourceTemplateStyleField : sourceTemplateStyleFields) {
                    if(targetTemplateStyleField.getBaseName().equals(sourceTemplateStyleField.getBaseName())) {
                        for(CardStyleFieldData cardStyleFieldData : cardStyleFieldDataList) {
                            if(cardStyleFieldData.getStyleFieldId().equals(sourceTemplateStyleField.getBaseId())) {
                                fieldValue = cardStyleFieldData.getStyleFieldValue();
                                break;
                            }
                        }
                        break;
                    }
                }
                newCardStyleFieldData.setStyleFieldValue(fieldValue);
                newCardStyleFieldDataList.add(newCardStyleFieldData);
            }
            // 删除名片原来的字段数据，并保存信息字段数据
            cardStyleFieldDataService.remove(new LambdaQueryWrapper<CardStyleFieldData>().eq(CardStyleFieldData::getCardId, cardId));
            if(!newCardStyleFieldDataList.isEmpty()) {
                cardStyleFieldDataService.saveBatch(newCardStyleFieldDataList);
            }
            // 删除原来的名片组件数据，并保存新的组件数据
            cardComponentDataService.remove(new LambdaQueryWrapper<CardComponentData>().eq(CardComponentData::getCardId, cardId));
            List<CardEnterpriseComponent> cardEnterpriseComponents = cardEnterpriseComponentMapper.queryCardEnterpriseComponentList(targetTemplateId);
            cardComponentDataService.createCardComponentData(cardEnterpriseComponents, cardId);
            // 修改名片表模板字段
            cardPersonalBaseInfoMapper.updateCardTemplateId(cardId, targetTemplateId, dto.getUserId());
            // 修改审批表模板字段
            cardAuditMapper.updateTemplateId(cardId, targetTemplateId, dto.getUserId());
        }
    }

    /**
     * 获取可以批量修改的名片字段列表。
     * @param templateId
     * @return
     */
    public List<StyleFieldDto> getBatchEditStyleFieldList(String templateId) {
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
        List<CardTemplateStyleFieldBo> templateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        List<StyleFieldDto> styleFieldList = new ArrayList<>();
        for(CardTemplateStyleFieldBo templateStyleField : templateStyleFields) {
            if(NewCardBusinessConstant.NO_EDIT_FIELD_LIST.contains(templateStyleField.getBaseName())) {
                continue;
            }
            StyleFieldDto styleField = new StyleFieldDto();
            styleField.setFieldId(templateStyleField.getBaseId());
            styleField.setFieldName(templateStyleField.getBaseName());

            styleFieldList.add(styleField);
        }
        return styleFieldList;
    }

    /**
     * 批量修改名片字段值
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateCardFieldValue(StyleFieldDto dto) {
        if(StrUtil.isBlank(dto.getFieldId()) || StrUtil.isBlank(dto.getFieldValue())) {
            throw new BusinessException("参数不能为空");
        }
        cardStyleFieldDataMapper.updateValueByFieldId(dto.getFieldId(), dto.getFieldValue());
    }

    /**
     * 修改模板名称
     * @param templateId
     * @param templateName
     * @param userId
     */
    public void updateTemplateName(String templateId, String templateName, String userId) {
        if(StrUtil.isBlank(templateId) || StrUtil.isBlank(templateName)) {
            throw new BusinessException("参数不能为空");
        }
        CardEnterpriseTemplateNew cardEnterpriseTemplateNew = new CardEnterpriseTemplateNew();
        cardEnterpriseTemplateNew.setBaseId(templateId);
        cardEnterpriseTemplateNew.setTemplateName(templateName);
        cardEnterpriseTemplateNew.setBaseUpdateBy(userId);
        cardEnterpriseTemplateNew.setBaseUpdateTime(new Date());
        cardEnterpriseTemplateNewMapper.updateById(cardEnterpriseTemplateNew);
    }

    /**
     * 查询模板下名片数量
     * @param enterpriseId
     * @param templateId
     * @return
     */
    public JSONObject getTemplateCardCount(String enterpriseId, String templateId) {
        Integer alreadyGetCardCount = cardAuditMapper.queryCardAuditCount(enterpriseId, templateId, NewCardBusinessConstant.CARD_STATUS_3);
        Integer noActiveCardCount = cardAuditMapper.queryCardAuditCount(enterpriseId, templateId, NewCardBusinessConstant.CARD_STATUS_1);
        Integer noAuditCardCount = cardAuditMapper.queryCardAuditCount(enterpriseId, templateId, NewCardBusinessConstant.CARD_STATUS_2);

        JSONObject jsonObject = new JSONObject();
        // 已经领取名片数量
        jsonObject.put("alreadyGetCardCount", alreadyGetCardCount);
        // 待激活数量
        jsonObject.put("noActiveCardCount", noActiveCardCount);
        // 待审核数量
        jsonObject.put("noAuditCardCount", noAuditCardCount);
        // 已加入数量，这个和已领取名片数量一样
        jsonObject.put("joinCount", alreadyGetCardCount);
        return jsonObject;
    }

    /**
     * 导入模板下载
     * @param enterpriseId
     * @param templateId
     * @param response
     */
    public void downloadImportExcelTemplate(String enterpriseId, String templateId, HttpServletResponse response) {
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
        List<CardTemplateStyleFieldBo> cardTemplateStyleFieldBos = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        List<String> fieldNameList = this.buildFieldNameList(cardTemplateStyleFieldBos);
        ServletOutputStream outputStream = null;
        try (InputStream templateStream = new ClassPathResource("file/企业名片导入模板.xlsx").getStream();
             Workbook book = WorkbookUtil.createBook(templateStream);
             ExcelWriter excelWriter = new ExcelWriter(book, "Sheet1")) {
            for (int i = 0; i < fieldNameList.size(); i++) {
                excelWriter.writeCellValue(i, 2, fieldNameList.get(i)); // 参数顺序：列索引，行索引，单元格值
            }
            String encodedFileName = URLEncoder.encode("企业名片导入模板.xlsx", "UTF-8").replaceAll("\\+", "%20");
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);
            outputStream = response.getOutputStream();
            excelWriter.flush(outputStream, true);
        }catch (Exception e) {
            log.error("下载导入模板异常：{}", ExceptionUtil.stacktraceToString(e));
            Message message = Message.fail("操作异常");
            this.sendJsonString(response, JSONObject.toJSONString(message));
        }finally {
            IOUtils.closeQuietly(outputStream);
        }
    }

    /**
     * 导出名片数据
     * @param templateId
     * @param status
     * @param response
     */
    public void exportTemplateCardData(String templateId, Integer status, HttpServletResponse response) {
        InputStream templateStream = null;
        Workbook book = null;
        ExcelWriter excelWriter;
        ServletOutputStream outputStream = null;
        int rowIndex = 2;
        try {
            templateStream = new ClassPathResource("file/企业名片导出模板.xlsx").getStream();
            book = WorkbookUtil.createBook(templateStream);
            excelWriter = new ExcelWriter(book, "Sheet1");
            CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
            List<CardTemplateStyleFieldBo> cardTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
            List<String> fieldNameList = this.buildFieldNameList(cardTemplateStyleFields);
            for (int i = 0; i < fieldNameList.size(); i++) {
                excelWriter.writeCellValue(i, rowIndex, fieldNameList.get(i)); // 参数顺序：列索引，行索引，单元格值
            }
            rowIndex++;
            List<String> cardIdList = cardAuditMapper.queryCardIdList(templateId, status);
            for(String cardId : cardIdList) {
                List<CardStyleFieldData> cardStyleFieldDataList = cardStyleFieldDataMapper.queryListByCardId(cardId);
                for(int columnIndex = 0; columnIndex < cardTemplateStyleFields.size(); columnIndex++) {
                    String fieldId = cardTemplateStyleFields.get(columnIndex).getBaseId();
                    String fieldValue = this.findExcelValue(fieldId, cardStyleFieldDataList);
                    excelWriter.writeCellValue(columnIndex, rowIndex, fieldValue);
                }
                rowIndex++;
            }
            String encodedFileName = URLEncoder.encode("名片数据.xlsx", "UTF-8").replaceAll("\\+", "%20");
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName);
            outputStream = response.getOutputStream();
            excelWriter.flush(outputStream, true);
            excelWriter.close();
        }catch (Exception e) {
            log.error("导出模板数据异常：{}", ExceptionUtil.stacktraceToString(e));
            Message message = Message.fail("导出数据异常");
            this.sendJsonString(response, JSONObject.toJSONString(message));
        }finally {
            IoUtil.close(book);
            IoUtil.close(templateStream);
            IoUtil.close(outputStream);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void importExcelData(String enterpriseId, String templateId, String userId, MultipartFile file) throws IOException{
        if(file.isEmpty()) {
            return;
        }
        String enterpriseVersion = null;
        Date expireTime = null;
        LuLianEnterprise luLianEnterprise = luLianEnterpriseMapper.selectById(enterpriseId);
        if(luLianEnterprise != null) {
            enterpriseVersion = String.valueOf(luLianEnterprise.getMiniProgramVersion());
            expireTime = luLianEnterprise.getExpireTime();
        }else {
            ShowEnterpriseTrial showEnterpriseTrial = showEnterpriseTrialMapper.selectById(enterpriseId);
            enterpriseVersion = String.valueOf(showEnterpriseTrial.getMiniProgramVersion());
            expireTime = showEnterpriseTrial.getExpireTime();
        }
        CardEnterpriseTemplate cardEnterpriseTemplate = cardEnterpriseTemplateMapper.queryEnterpriseTemplateInfo(templateId);
        List<CardTemplateStyleFieldBo> cardTemplateStyleFields = cardTemplateStyleFieldMapper.queryListByOldTemplateId(cardEnterpriseTemplate.getBaseId());
        List<CardEnterpriseComponent> templateComponentList = cardEnterpriseComponentMapper.queryCardEnterpriseComponentList(templateId);
        ImportExcelCardDataRowHandler wrapper = new ImportExcelCardDataRowHandler(cardTemplateStyleFields, templateComponentList, userId, enterpriseId, templateId, enterpriseVersion, expireTime);
        ExcelUtil.readBySax(file.getInputStream(), 0, wrapper);
        if(!wrapper.getSuccess()) {
            throw new BusinessException(wrapper.getErrorMsg());
        }
        // 校验导入的这些手机号是否已经存在。这些手机号可能有的还没创建账号
        // 在已审核、待审核、待激活中是否已经有存在的
        if(CollectionUtil.isNotEmpty(wrapper.getMobileSet())) {
            Integer userExistCount = cardAuditMapper.queryEnterpriseUserCardByMobileList(enterpriseId, templateId, wrapper.getMobileSet());
            if (userExistCount > 0) {
                throw new BusinessException("导入的数据中部分手机号已经在该模板下存在");
            }
            // 校验这些导入的手机号所对应的用户id是否在模板下已经存在
            List<String> userIdList = gxmhSysMapper.queryUserIdListByMobileList(wrapper.getMobileSet());
            if(CollectionUtil.isNotEmpty(userIdList)) {
                Integer userIdExistCount = cardAuditMapper.queryEnterpriseUserCardByUserIdList(enterpriseId, templateId, userIdList);
                if (userIdExistCount > 0) {
                    throw new BusinessException("导入的数据中部分手机号已经在该模板下的已审核或待审核列表中存在");
                }
            }
        }

        // 统一保存数据
        cardPersonalBaseInfoService.saveBatch(wrapper.getCardBaseInfoList());
        cardStyleFieldDataService.saveBatch(wrapper.getCardStyleFieldDataList());
        cardComponentDataService.saveBatch(wrapper.getCardComponentDataList());
        cardAuditService.saveBatch(wrapper.getCardAuditList());
    }

    /**
     * 小程序端--查询企业名片使用情况
     * @param enterpriseId
     * @return
     */
    public EnterpriseCardUseInfoVo queryEnterpriseCardUseInfo(String enterpriseId) {
        EnterpriseCardUseInfoVo vo = new EnterpriseCardUseInfoVo();
        String expireTime = null;
        LuLianEnterprise luLianEnterprise = luLianEnterpriseMapper.selectById(enterpriseId);
        if(luLianEnterprise != null) {
            expireTime = DateUtil.format(luLianEnterprise.getExpireTime(), DatePattern.NORM_DATE_FORMAT);
        }else {
            ShowEnterpriseTrial showEnterpriseTrial = showEnterpriseTrialMapper.selectById(enterpriseId);
            expireTime = DateUtil.format(showEnterpriseTrial.getExpireTime(), DatePattern.NORM_DATE_FORMAT);
        }
        vo.setExpiredTime(expireTime);
        Integer alreadyGetCardCount = cardAuditMapper.queryCardAuditCount(enterpriseId, null, NewCardBusinessConstant.CARD_STATUS_3);
        vo.setAlreadyGetCardCount(alreadyGetCardCount);
        // 转发数量
        vo.setShareCount(cardPersonalBaseInfoMapper.queryEnterpriseCardShareCount(enterpriseId));
        // 访问数量
        vo.setViewCount(cardPersonalBaseInfoMapper.queryEnterpriseCardViewCount(enterpriseId));
        return vo;
    }

    /**
     * 小程序端--查询企业下用户名片使用情况
     * @param dto
     * @return
     */
    public PageResult<EnterpriseUserCardUseInfoVo> queryEnterpriseUserCardUseInfo(EnterpriseUserCardUseInfoDto dto) {
        if(StrUtil.isEmpty(dto.getType())) {
            throw new BusinessException("请选择时间类型：day, week,month,year,range");
        }
        Date now = new Date();
        if("day".equals(dto.getType())) {
            String day = DateUtil.format(now, DatePattern.NORM_DATE_FORMAT);
            dto.setStartTime(day);
            dto.setEndTime(day);
        } else if("week".equals(dto.getType())) {
            String weekStartTime = DateUtil.format(DateUtil.beginOfWeek(now), DatePattern.NORM_DATE_FORMAT);
            String weekEndTime = DateUtil.format(DateUtil.endOfWeek(now), DatePattern.NORM_DATE_FORMAT);
            dto.setStartTime(weekStartTime);
            dto.setEndTime(weekEndTime);
        } else if("month".equals(dto.getType())) {
            String monthStartTime = DateUtil.format(DateUtil.beginOfMonth(now), DatePattern.NORM_DATE_FORMAT);
            String monthEndTime = DateUtil.format(DateUtil.endOfMonth(now), DatePattern.NORM_DATE_FORMAT);
            dto.setStartTime(monthStartTime);
            dto.setEndTime(monthEndTime);
        }else if("range".equals(dto.getType())) {
            if(StrUtil.isBlank(dto.getStartTime()) && StrUtil.isBlank(dto.getEndTime())) {
                throw new BusinessException("请选择时间范围");
            }
        }
        dto.setStartTime(dto.getStartTime() + " 00:00:00");
        dto.setEndTime(dto.getEndTime() + " 23:59:59");
        IPage<EnterpriseUserCardUseInfoVo> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        List<EnterpriseUserCardUseInfoVo> list = cardPersonalBaseInfoMapper.queryEnterpriseUserCardUseInfo(page, dto);
        PageResult<EnterpriseUserCardUseInfoVo> pageResult = new PageResult<>(list, new PageInfo(dto.getPageNum(), dto.getPageSize()), page.getTotal());
        return pageResult;
    }

    /**
     * 判断企业是否过期
     * @param enterpriseId
     * @return true 已过期
     */
    public Boolean getEnterpriseOverdue(String enterpriseId) {
        Date expireTime = null;
        LuLianEnterprise luLianEnterprise = luLianEnterpriseMapper.selectById(enterpriseId);
        if(luLianEnterprise != null) {
            expireTime = luLianEnterprise.getExpireTime();
        }else {
            ShowEnterpriseTrial showEnterpriseTrial = showEnterpriseTrialMapper.selectById(enterpriseId);
            expireTime = showEnterpriseTrial.getExpireTime();
        }
        if(expireTime == null) {
            throw new BusinessException("未查询到企业的过期时间");
        }
        LocalDate now = LocalDate.now();
        LocalDate expireLocalDate = LocalDate.parse(DateUtil.format(expireTime, DatePattern.NORM_DATE_FORMAT));
        // 过期时间已过返回true
        return now.isAfter(expireLocalDate);
    }

    /**
     * 判断用户是否在某模板下已经存在名片
     * 审核通过的，返回true
     * 若有待审核的名片，也返回false，此时用户仍然在小程序端填写表单，提交的时候会判断（无法提交）
     * 若有待激活的名片，此时用户仍然在小程序端填写表单，提交的时候会判断，可以提交到待审核列表。
     *  原本待激活的数据在激活的时候会无法激活
     * @param enterpriseId
     * @param templateId
     * @param userId
     * @return 如果模板下存在了用户的名片返回true
     */
    public Boolean userExistTemplate(String enterpriseId, String templateId, String userId) {
        // 这个查询只能查询待审核和审核通过的
        String existCardId = cardPersonalBaseInfoMapper.queryEnterpriseCardId(enterpriseId, templateId, userId);
        if(StrUtil.isEmpty(existCardId)) {
            return false;
        }
        CardAudit cardAudit = cardAuditMapper.queryCardAuditInfoByCardId(existCardId);
        // 只有已审核通过的时候是true
        if(NewCardBusinessConstant.CARD_STATUS_3.equals(cardAudit.getCardStatus())) {
            return true;
        }
        return false;
    }

    private String findExcelValue(String fieldId, List<CardStyleFieldData> cardStyleFieldDataList) {
        for(CardStyleFieldData CardStyleFieldData : cardStyleFieldDataList) {
            if(fieldId.equals(CardStyleFieldData.getStyleFieldId())) {
                return CardStyleFieldData.getStyleFieldValue();
            }
        }
        return "";
    }

    private List<StyleFieldDto> getStyleFieldDtoList(List<CardTemplateStyleFieldBo> targetTemplateStyleFields, List<StyleFieldDto> sourceStyleFieldDtoList) {
        List<StyleFieldDto> targetStyleFieldDtoList = new ArrayList<>();
        for(CardTemplateStyleFieldBo targetTemplateStyleFieldBo : targetTemplateStyleFields) {
            StyleFieldDto styleFieldDto = new StyleFieldDto();
            styleFieldDto.setFieldId(targetTemplateStyleFieldBo.getBaseId());
            String fieldName = targetTemplateStyleFieldBo.getBaseName();
            styleFieldDto.setFieldName(fieldName);
            styleFieldDto.setFieldType(targetTemplateStyleFieldBo.getFieldType());
            String fieldValue = "";
            for(StyleFieldDto sourceStyleFieldDto : sourceStyleFieldDtoList) {
                // 字段名称相同
                if(fieldName.equals(sourceStyleFieldDto.getFieldName())) {
                    fieldValue = sourceStyleFieldDto.getFieldValue();
                    break;
                }
            }
            styleFieldDto.setFieldValue(fieldValue);
            styleFieldDto.setRequiredFlag(targetTemplateStyleFieldBo.getRequiredFlag()?1:0);
            //styleFieldDto.setFieldEngName(IdUtil.simpleUUID());
            targetStyleFieldDtoList.add(styleFieldDto);
        }
        return targetStyleFieldDtoList;
    }

    private void replaceTemplateTextValue(List<CardTemplateStyleFieldBo> cardTemplateStyleFields, List<CardStyleFieldData> cardStyleFieldDataList) {
        for(CardTemplateStyleFieldBo cardTemplateStyleField : cardTemplateStyleFields) {
            boolean find = false;
            for(CardStyleFieldData cardStyleFieldData : cardStyleFieldDataList) {
                if(cardTemplateStyleField.getBaseId().equals(cardStyleFieldData.getStyleFieldId())) {
                    find = true;
                    JSONObject jsonObject = JSONObject.parseObject(cardTemplateStyleField.getExtraInfo());
                    if(jsonObject.containsKey("text")) {
                        jsonObject.put("text", StrUtil.isEmpty(cardStyleFieldData.getStyleFieldValue()) ? "" : cardStyleFieldData.getStyleFieldValue());
                    }
                    cardTemplateStyleField.setExtraInfo(jsonObject.toJSONString());
                }
            }
            if(!find) {
                JSONObject jsonObject = JSONObject.parseObject(cardTemplateStyleField.getExtraInfo());
                if(jsonObject.containsKey("text")) {
                    jsonObject.put("text", "");
                }
                cardTemplateStyleField.setExtraInfo(jsonObject.toJSONString());
            }
        }
    }

    // 将目标模板字段样式的json内容中，text的值替换为字段value数据
    private void dealStyleFieldExtInfo(List<CardTemplateStyleFieldBo> targetTemplateStyleFields, List<StyleFieldDto> targetStyleFieldDtoList) {
        for(CardTemplateStyleFieldBo cardTemplateStyleField : targetTemplateStyleFields) {
            boolean find = false;
            for(StyleFieldDto styleFieldDto : targetStyleFieldDtoList) {
                if(cardTemplateStyleField.getBaseId().equals(styleFieldDto.getFieldId())) {
                    find = true;
                    JSONObject jsonObject = JSONObject.parseObject(cardTemplateStyleField.getExtraInfo());
                    if(jsonObject.containsKey("text")) {
                        jsonObject.put("text", StrUtil.isEmpty(styleFieldDto.getFieldValue()) ? "" : styleFieldDto.getFieldValue());
                    }
                    cardTemplateStyleField.setExtraInfo(jsonObject.toJSONString());
                }
            }
            if(!find) {
                JSONObject jsonObject = JSONObject.parseObject(cardTemplateStyleField.getExtraInfo());
                if(jsonObject.containsKey("text")) {
                    jsonObject.put("text", "");
                }
                cardTemplateStyleField.setExtraInfo(jsonObject.toJSONString());
            }
        }
    }

    private List<String> buildFieldNameList(List<CardTemplateStyleFieldBo> cardTemplateStyleFields) {
        List<String> fieldList = new ArrayList<>();
        for(CardTemplateStyleFieldBo cardTemplateStyleField : cardTemplateStyleFields) {
            String name = cardTemplateStyleField.getBaseName();
            if(cardTemplateStyleField.getRequiredFlag()) {
                fieldList.add( name + MUST_FILL);
            }else {
                fieldList.add(name);
            }
        }
        return fieldList;
    }

    // 加入待审核列表
    private CardAudit addToAudit(String enterpriseId, String templateId, String cardId, String userId, Integer cardStatus) {
        CardAudit cardAudit = new CardAudit();
        cardAudit.setBaseId(IdUtil.simpleUUID());
        cardAudit.setEnterpriseId(enterpriseId);
        cardAudit.setTemplateId(templateId);
        cardAudit.setCardId(cardId);
        cardAudit.setCardStatus(cardStatus);
        cardAudit.setBaseCreateBy(userId);
        cardAudit.setBaseUpdateBy(userId);
        cardAudit.setBaseCreateTime(new Date());
        cardAudit.setBaseUpdateTime(new Date());
        cardAudit.setUserId(userId);
        return cardAudit;
    }

    // 绑定用户和企业
    private void bindEnterprise(String enterpriseId, String userId) {
        Integer count = luLianEnterpriseMapper.queryEnterpriseUserCount(enterpriseId, userId);
        if(count > 0) {
            return;
        }
        LuLianEnterpriseUser enterpriseUser = LuLianEnterpriseUser.builder().enterpriseId(enterpriseId).baseId(IdUtil.simpleUUID()).userId(userId).build();
        luLianEnterpriseUserMapper.insert(enterpriseUser);
    }

    private void insertUserRole(String enterpriseId, String userId) {
        // 个人角色
        Integer personRoleCount = gxmhSysMapper.queryUserRoleCount(enterpriseId, userId, "c297ac5995d941d2b0b05c2048747713");
        if(personRoleCount > 0) {
            return;
        }
        gxmhSysMapper.insertUserRoleEnterrpise(IdUtil.simpleUUID(), userId, "c297ac5995d941d2b0b05c2048747713", enterpriseId);
    }

    // 创建名片字段数据
    private void createCardFieldData(CreateEnterpriseUserCardDto dto, String cardId) {
        List<CardStyleFieldData> cardStyleFieldDataList = new ArrayList<>();
        for(StyleFieldDto styleFieldDto : dto.getStyleFieldList()) {
            CardStyleFieldData cardStyleFieldData = new CardStyleFieldData();
            cardStyleFieldData.setBaseId(IdUtil.simpleUUID());
            cardStyleFieldData.setCardId(cardId);
            cardStyleFieldData.setStyleFieldId(styleFieldDto.getFieldId());
            cardStyleFieldData.setStyleFieldValue(styleFieldDto.getFieldValue());
            cardStyleFieldDataList.add(cardStyleFieldData);
        }
        if(!cardStyleFieldDataList.isEmpty()) {
            cardStyleFieldDataService.saveBatch(cardStyleFieldDataList);
        }
    }

    private void updateCardBaseInfo(String cardId, CreateEnterpriseUserCardDto dto) {
        CardBaseInfo cardBaseInfo = new CardBaseInfo();
        cardBaseInfo.setBaseId(dto.getCardId());
        boolean updateBaseInfoFlag = false;
        for(StyleFieldDto styleFieldDto : dto.getStyleFieldList()) {
            if("手机".equals(styleFieldDto.getFieldName())) {
                updateBaseInfoFlag = true;
                cardBaseInfo.setEnterpriseMobile(styleFieldDto.getFieldValue());
            }else if("邮箱".equals(styleFieldDto.getFieldName())) {
                updateBaseInfoFlag = true;
                cardBaseInfo.setEnterpriseEmail(styleFieldDto.getFieldValue());
            } else if("姓名".equals(styleFieldDto.getFieldName())) {
                updateBaseInfoFlag = true;
                cardBaseInfo.setName(styleFieldDto.getFieldValue());
            } else if("职位".equals(styleFieldDto.getFieldName())) {
                updateBaseInfoFlag = true;
                cardBaseInfo.setPositionOne(styleFieldDto.getFieldValue());
            }
        }
        if(updateBaseInfoFlag) {
            cardPersonalBaseInfoService.updateById(cardBaseInfo);
        }
    }

    private CardBaseInfo buildCardBaseInfo(CreateEnterpriseUserCardDto dto) {
        // 查询当前企业的版本和过期时间
        String enterpriseName = "";
        Date expireTime = null;
        Integer enterpriseVersion = null;
        LuLianEnterprise luLianEnterprise = luLianEnterpriseMapper.selectById(dto.getEnterpriseId());
        if(luLianEnterprise == null) {
            ShowEnterpriseTrial showEnterpriseTrial = showEnterpriseTrialMapper.selectById(dto.getEnterpriseId());
            enterpriseName = showEnterpriseTrial.getBaseName();
            expireTime = showEnterpriseTrial.getExpireTime();
            enterpriseVersion = showEnterpriseTrial.getMiniProgramVersion();
        }else {
            enterpriseName = luLianEnterprise.getBaseName();
            expireTime = luLianEnterprise.getExpireTime();
            enterpriseVersion = luLianEnterprise.getMiniProgramVersion();
        }
        Date now = new Date();
        CardBaseInfo cardBaseInfo = new CardBaseInfo();
        cardBaseInfo.setBaseId(IdUtil.simpleUUID());
        // 领取名片时没有这个字段
        //cardBaseInfo.setEnterpriseUseType();
        cardBaseInfo.setName(this.findFormValue("姓名", dto.getStyleFieldList()));
        cardBaseInfo.setEnterpriseId(dto.getEnterpriseId());
        cardBaseInfo.setUserId(dto.getUserId());
        cardBaseInfo.setTemplateId(dto.getTemplateId());
        cardBaseInfo.setEnterpriseName(enterpriseName);
        cardBaseInfo.setPositionOne(this.findFormValue("职位", dto.getStyleFieldList()));
        cardBaseInfo.setEnterpriseMobile(this.findFormValue("手机", dto.getStyleFieldList()));
        cardBaseInfo.setEnterpriseEmail(this.findFormValue("邮箱", dto.getStyleFieldList()));
        cardBaseInfo.setCardVersion(MiniProgramVersionConstant.getCardVersionByEnterpriseVersion(enterpriseVersion));
        cardBaseInfo.setExpireTime(expireTime);
        cardBaseInfo.setUseResourceType(NewCardBusinessConstant.CARD_USE_RESOURCE_TYPE_3);
        cardBaseInfo.setBaseCreateBy(dto.getUserId());
        cardBaseInfo.setBaseCreateTime(now);
        cardBaseInfo.setBaseUpdateBy(dto.getUserId());
        cardBaseInfo.setBaseUpdateTime(now);
        cardBaseInfo.setIsDelete(0);
        // 设置是否当前在用
        Integer currentUse = cardPersonalBaseInfoMapper.queryCurrentUseCardCount(dto.getUserId());
        cardBaseInfo.setCurrentUse(currentUse == 0 ? 1 : 0);
        return cardBaseInfo;
    }

    private String findFormValue(String fieldName, List<StyleFieldDto> styleFieldList) {
        for(StyleFieldDto dto : styleFieldList) {
            if(fieldName.equals(dto.getFieldName())) {
                return dto.getFieldValue();
            }
        }
        return "";
    }

    private String findValue(List<CardStyleFieldData> cardStyleFieldData, CardFieldBo nameField) {
        for(CardStyleFieldData data : cardStyleFieldData) {
            if(nameField.getFieldId().equals(data.getStyleFieldId())) {
                return data.getStyleFieldValue();
            }
        }
        return "";
    }

    private String findValue2(List<CardStyleFieldData> cardStyleFieldData, String fieldId) {
        for(CardStyleFieldData data : cardStyleFieldData) {
            if(fieldId.equals(data.getStyleFieldId())) {
                return data.getStyleFieldValue();
            }
        }
        return "";
    }


    // 判断字段是否存在
    private CardFieldBo existFieldName(String fieldName, List<CardTemplateStyleFieldBo> cardTemplateStyleFields) {
        CardFieldBo cardFieldBo = new CardFieldBo();
        if(CollectionUtil.isEmpty(cardTemplateStyleFields)) {
            cardFieldBo.setExist(false);
            return cardFieldBo;
        }
        for (CardTemplateStyleFieldBo field : cardTemplateStyleFields) {
            if(fieldName.equals(field.getBaseName())) {
                cardFieldBo.setExist(true);
                cardFieldBo.setFieldId(field.getBaseId());
                return cardFieldBo;
            }
        }
        cardFieldBo.setExist(false);
        return cardFieldBo;
    }

    private Message checkParam(CreateEnterpriseUserCardDto dto) {
        if(StrUtil.isEmpty(dto.getEnterpriseId())) {
            return Message.fail("企业标识不能为空");
        }
        if(StrUtil.isEmpty(dto.getTemplateId())) {
            return Message.fail("模板标识不能为空");
        }
        if(StrUtil.isEmpty(dto.getUserId())) {
            return Message.fail("用户标识不能为空");
        }
        return null;
    }
    private void sendJsonString(HttpServletResponse response, String jsonString) {
        try {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(jsonString);
        } catch (Exception e) {
            log.error("发送json字符串异常：{}", ExceptionUtil.stacktraceToString(e));
        }
    }

}
